Ext.Template = Ext.extend(Object, {

    //构造函数
    constructor: function(html) {
        var me = this,
            args = arguments,
            buffer = [],
            value, i, length;
            
        me.initialConfig = {};

        // 如果模版是数组
        if (Ext.isArray(html)) {
            html = html.join("");
        }
        else if (args.length > 1) {

            // 如果多参数
            for (i = 0, length = args.length; i < length; i++) {
                value = args[i];

                // 当前参数是对象，则混入initialConfig和自身
                if (typeof value == 'object') {
                    Ext.apply(me.initialConfig, value);
                    Ext.apply(me, value);
                } else {
                    buffer.push(value); // 否则
                }
            }
            html = buffer.join('');
        }

        // html模版内容
        me.html = html;
        
        // 如果要立即编译
        if (me.compiled) {
            me.compile();
        }
    },
    isTemplate: true,  
    
    disableFormats: false,
    
    //<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>
    re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,      
    
    // 模版数据统一编译
    applyTemplate: function(values) {
        var me = this,
            useFormat = me.disableFormats !== true,
            fm = Ext.util.Format,
            tpl = me;

        // 如果已经编译出compiled方法，直接运行compiled方法编译
        if (me.compiled) {
            return me.compiled(values);
        }
        function fn(m, name, format, args) {
            if (format && useFormat) {
                if (args) {
                    args = [values[name]].concat(new Function('return ['+ args +'];')());
                } else {
                    args = [values[name]];
                }
                if (format.substr(0, 5) == "this.") {
                    return tpl[format.substr(5)].apply(tpl, args);
                }
                else {
                    return fm[format].apply(fm, args);
                }
            }
            else {
                return values[name] !== undefined ? values[name] : "";
            }
        }
        return me.html.replace(me.re, fn); // 模版编译
    },

    // 重置模版
    set: function(html, compile) {
        var me = this;
        me.html = html;
        me.compiled = null;
        return compile ? me.compile() : me;
    },
    
    compileARe: /\\/g,
    compileBRe: /(\r\n|\n)/g,
    compileCRe: /'/g,

    // 预编译出处理模版和数据的方法
    compile: function() {
        var me = this,
            fm = Ext.util.Format,
            useFormat = me.disableFormats !== true,
            body, bodyReturn;

        // 替换函数
        // {cls}: "{cls}", "cls", undefined, undefined, 13, 要查询的字符串
        // {name:trim}: "{name:trim}", "name", "trim", undefined, 20, 要查询的字符串
        // {value:ellipsis(10)}: "{value:ellipsis(10)}", "value", "ellipsis", "10", 32, 要查询的字符串
        function fn(m, name, format, args) {

            // 有健值对的值，且没禁用格式化
            if (format && useFormat) {

                args = args ? ',' + args: ""; // 是否有参数（有参数说明是表达式）

                // 如果值没有this.前缀
                if (format.substr(0, 5) != "this.") {
                    format = "fm." + format + '(';
                }
                else {
                    format = 'this.' + format.substr(5) + '(';
                }
            }
            else {
                args = '';
                format = "(values['" + name + "'] == undefined ? '' : "; // 没有值，或者不格式化的情况下，
            }
            return "'," + format + "values['" + name + "']" + args + ") ,'";
        }

        // 将特殊字符编译成转义字符，并返回方法体字符串
        bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn);
        body = "this.compiled = function(values){ return ['" + bodyReturn + "'].join('');};";

        eval(body); // 运行方法体，将编译方法赋予this.compiled

        return me;
    },

    // 将values生成的html片段以向前追加的形式放入el内，returnElement决定返回element还是node
    insertFirst: function(el, values, returnElement) {
        return this.doInsert('afterBegin', el, values, returnElement);
    },

    // 将values生成的html片段以兄弟节点的形式紧贴在el前面
    insertBefore: function(el, values, returnElement) {
        return this.doInsert('beforeBegin', el, values, returnElement);
    },

    // 将values生成的html片段以兄弟节点的形式紧跟在el后面
    insertAfter: function(el, values, returnElement) {
        return this.doInsert('afterEnd', el, values, returnElement);
    },

    // 将values生成的html片段以向后追加的形式放入el内，returnElement决定返回element还是node
    append: function(el, values, returnElement) {
        return this.doInsert('beforeEnd', el, values, returnElement);
    },

    // 生成html片段并插入页面内
    doInsert: function(where, el, values, returnEl) {
        el = Ext.getDom(el);
        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
        return returnEl ? Ext.get(newNode, true) : newNode;
    },

    // 将values生成的html片段覆盖el内的innerHTML
    overwrite: function(el, values, returnElement) {
        el = Ext.getDom(el);
        el.innerHTML = this.applyTemplate(values);
        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
    }
});

// 模版数据统一编译
Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;

// 从dom节点的value或者innerHTML中拿到模版（value一般为textarea里的内容，innerHTML一般是script标签中的内容）
Ext.Template.from = function(el, config) {
    el = Ext.getDom(el);
    return new Ext.Template(el.value || el.innerHTML, config || '');
};